KDOC 94: 2>&1の意味

この文書のステータス

  • 作成
    • 2024-02-14 貴島
  • レビュー
    • 2024-02-18 貴島

概要

Shellに、標準出力と標準エラーをまとめる 2>&1 という書き方がある。よくコマンドの実行結果を保存するのに使う。標準出力と、標準エラー出力をまとめて取り出せるとデバッグに便利である。よくわからずに使っていたので、記法の意味を分解して理解する。

動かしてみる

まず使い方をまとめ、実行して分解を試みる。

result=`echo "hello" 2>&1`
echo $result
hello
result=`aaa 2>&1`
echo $result
/bin/bash: line 1: aaa: command not found
result=`aaa 2>1`
cat 1
/bin/bash: line 1: aaa: command not found
result=`aaa 2>& 1`
echo $result
/bin/bash: line 1: aaa: command not found
result=`aaa 2> &1`
echo $result

結論、 2>& はスペースを許容せずひと塊でないといけない。意味的にもひと塊になっているはずだが、意味のつながりがよくわからない。

調べる

Bashのリダイレクト(`>`と`>&`)とパイプ等についてのまとめ #Bash - Qiitaを見てみよう。

> はリダイレクト記法である。空のファイルを生成して書き込む。書式は $ コマンド [元fd=1]> 先ファイル名 となっている。ファイルディスクリプタ番号はデフォルトで1(標準出力)。

echo "hello1" > test.log
cat test.log

echo "hello2" 1> test.log
cat test.log
hello1
hello2
aaa 2> error.log
cat error.log
/bin/bash: line 1: aaa: command not found

>& は他のファイルディスクリプタにリダイレクトする。 $コマンド [元FD]>&[先FD] 。&がないとファイル書き込みになってしまう。つまり 2>&1 は標準エラー出力を標準出力にリダイレクトする。結果、標準出力に標準出力と標準エラー出力が表示できる。

result=`echo hello 2>&1`
echo $result
hello
result=`aaa 2>&1`
echo $result
/bin/bash: line 1: aaa: command not found

リダイレクトをさらにリダイレクトできる。

result=`echo hello 2>&1 > aaa.log`
cat aaa.log
hello
result=`echo hello 2>&1 > /dev/null`
echo $result

以上より、 2>& がひと塊でないといけない理由。

  • 2> の数字はリダイレクト元ファイルディスクリプタ指定。 >1> が省略されているだけで、1以外には 2> と省略せずに書く必要がある。そもそもスペースは入れない記法である
  • >&& は続くリダイレクト先がファイルディスクリプタであることを示す。 > に続く識別子がファイル名でないのを区別するための記法なので、スペースを許容しないほうが意味が明確である。ファイル名は & がくる可能性があり、そのとき意味が不明瞭になる

参考

関連

なし。